-
Notifications
You must be signed in to change notification settings - Fork 0
/
code.js
277 lines (234 loc) · 6.26 KB
/
code.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
// The snake moves along a grid, one space at a time
// The grid is smaller than the canvas, and its dimensions
// are stored in these variables
let gridWidth = 30;
let gridHeight = 30;
let gameStarted = false;
// How many segments snake starts with
let startingSegments = 10;
// Starting coordinates for first segment
let xStart = 0;
let yStart = 15;
// Starting direction of motion
let startDirection = 'right';
// Current direction of motion
let direction = startDirection;
// The snake is divided into small segments,
// stored as vectors in this array
let segments = [];
let score = 0;
let highScore;
// The fruit's position is stored as a vector
// in this variable
let fruit;
function setup() {
createCanvas(500, 500);
// Adjust frame rate to set movement speed
frameRate(10);
textAlign(CENTER, CENTER);
textSize(2);
// Check for saved high score in local browser storage
// If no score has been stored, this will be undefined
highScore = getItem('high score');
describe(
'A reproduction of the arcade game Snake, in which a snake, represented by a green line on a black background, is controlled by the arrow keys. Users move the snake toward a fruit, represented by a red dot, but the snake must not hit the sides of the window or itself.'
);
}
function draw() {
background(0);
// Set scale so that the game grid fills canvas
scale(width / gridWidth, height / gridHeight);
if (gameStarted === false) {
showStartScreen();
} else {
// Shift over so that snake and fruit are still on screen
// when their coordinates are 0
translate(0.5, 0.5);
showFruit();
showSegments();
updateSegments();
checkForCollision();
checkForFruit();
}
}
function showStartScreen() {
noStroke();
fill(32);
rect(2, gridHeight / 2 - 5, gridWidth - 4, 10, 2);
fill(255);
text(
'Click to play.\nUse arrow keys to move.',
gridWidth / 2,
gridHeight / 2
);
noLoop();
}
function mousePressed() {
if (gameStarted === false) {
startGame();
}
}
function startGame() {
// Put the fruit in a random place
updateFruitCoordinates();
// Start with an empty array for segments
segments = [];
// Start with x at the starting position and repeat until specified
// number of segments have been created, increasing x by 1 each time
for (let x = xStart; x < xStart + startingSegments; x += 1) {
// Create a new vector at the current position
let segmentPosition = createVector(x, yStart);
// Add it to the beginning of the array
segments.unshift(segmentPosition);
}
direction = startDirection;
score = 0;
gameStarted = true;
loop();
}
function showFruit() {
stroke(255, 64, 32);
point(fruit.x, fruit.y);
}
function showSegments() {
noFill();
stroke(96, 255, 64);
beginShape();
for (let segment of segments) {
vertex(segment.x, segment.y);
}
endShape();
}
function updateSegments() {
// Remove last segment
segments.pop();
// Copy current head of snake
let head = segments[0].copy();
// Insert the new snake head at the beginning of the array
segments.unshift(head);
// Adjust the head's position based on the current direction
switch (direction) {
case 'right':
head.x = head.x + 1;
break;
case 'up':
head.y = head.y - 1;
break;
case 'left':
head.x = head.x - 1;
break;
case 'down':
head.y = head.y + 1;
break;
}
}
function checkForCollision() {
// Store first segment in array as head
let head = segments[0];
// If snake's head...
if (
// hit right edge or
head.x >= gridWidth ||
// hit left edge or
head.x < 0 ||
// hit bottom edge or
head.y >= gridHeight ||
// hit top edge or
head.y < 0 ||
// collided with itself
selfColliding() === true
) {
// show game over screen
gameOver();
}
}
function gameOver() {
noStroke();
fill(32);
rect(2, gridHeight / 2 - 5, gridWidth - 4, 12, 2);
fill(255);
// Set high score to whichever is larger: current score or previous
// high score
highScore = max(score, highScore);
// Put high score in local storage. This will be be stored in browser
// data, even after the user reloads the page.
storeItem('high score', highScore);
text(
`Game over!
Your score: ${score}
High score: ${highScore}
Click to play again.`,
gridWidth / 2,
gridHeight / 2
);
gameStarted = false;
noLoop();
}
function selfColliding() {
// Store the last segment as head
let head = segments[0];
// Store every segment except the first
let segmentsAfterHead = segments.slice(1);
// Check each of the other segments
for (let segment of segmentsAfterHead) {
// If segment is in the same place as head
if (segment.equals(head) === true) {
return true;
}
}
return false;
}
function checkForFruit() {
// Store first segment as head
let head = segments[0];
// If the head segment is in the same place as the fruit
if (head.equals(fruit) === true) {
// Give player a point
score = score + 1;
// Duplicate the tail segment
let tail = segments[segments.length - 1];
let newSegment = tail.copy();
// Put the duplicate in the beginning of the array
segments.push(newSegment);
// Reset fruit to a new location
updateFruitCoordinates();
}
}
function updateFruitCoordinates() {
// Pick a random new coordinate for the fruit
// and round it down using floor().
// Because the segments move in increments of 1,
// in order for the snake to hit the same position
// as the fruit, the fruit's coordinates must be
// integers, but random() returns a float
let x = floor(random(gridWidth));
let y = floor(random(gridHeight));
fruit = createVector(x, y);
}
// When an arrow key is pressed, switch the snake's direction of movement,
// but if the snake is already moving in the opposite direction,
// do nothing.
function keyPressed() {
switch (keyCode) {
case LEFT_ARROW:
if (direction !== 'right') {
direction = 'left';
}
break;
case RIGHT_ARROW:
if (direction !== 'left') {
direction = 'right';
}
break;
case UP_ARROW:
if (direction !== 'down') {
direction = 'up';
}
break;
case DOWN_ARROW:
if (direction !== 'up') {
direction = 'down';
}
break;
}
}